package com.codeplatform.service;

import com.codeplatform.dto.CodeExecutionResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 * 用于实时推送代码执行状态和结果
 * 
 * @author CodePlatform
 * @since 2024-01-01
 */
@Slf4j
@Service
public class WebSocketService {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 推送代码执行开始消息
     * 
     * @param sessionId 会话ID
     * @param language 编程语言
     */
    public void sendExecutionStart(String sessionId, String language) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "execution_start");
            message.put("sessionId", sessionId);
            message.put("language", language);
            message.put("timestamp", System.currentTimeMillis());
            message.put("status", "开始执行代码...");

            // 发送到特定会话
            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送代码执行开始消息: sessionId={}, language={}", sessionId, language);
        } catch (Exception e) {
            log.error("发送代码执行开始消息失败", e);
        }
    }

    /**
     * 推送代码编译状态消息
     * 
     * @param sessionId 会话ID
     * @param compileInfo 编译信息
     * @param success 编译是否成功
     */
    public void sendCompileStatus(String sessionId, String compileInfo, boolean success) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "compile_status");
            message.put("sessionId", sessionId);
            message.put("compileInfo", compileInfo);
            message.put("success", success);
            message.put("timestamp", System.currentTimeMillis());
            message.put("status", success ? "编译成功" : "编译失败");

            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送编译状态消息: sessionId={}, success={}", sessionId, success);
        } catch (Exception e) {
            log.error("发送编译状态消息失败", e);
        }
    }

    /**
     * 推送代码执行进度消息
     * 
     * @param sessionId 会话ID
     * @param progress 执行进度 (0-100)
     * @param status 状态描述
     */
    public void sendExecutionProgress(String sessionId, int progress, String status) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "execution_progress");
            message.put("sessionId", sessionId);
            message.put("progress", progress);
            message.put("status", status);
            message.put("timestamp", System.currentTimeMillis());

            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送执行进度消息: sessionId={}, progress={}%, status={}", sessionId, progress, status);
        } catch (Exception e) {
            log.error("发送执行进度消息失败", e);
        }
    }

    /**
     * 推送代码执行结果消息
     * 
     * @param sessionId 会话ID
     * @param result 执行结果
     */
    public void sendExecutionResult(String sessionId, CodeExecutionResult result) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "execution_result");
            message.put("sessionId", sessionId);
            message.put("result", result);
            message.put("timestamp", System.currentTimeMillis());
            message.put("status", result.getSuccess() ? "执行完成" : "执行失败");

            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送执行结果消息: sessionId={}, success={}", sessionId, result.getSuccess());
        } catch (Exception e) {
            log.error("发送执行结果消息失败", e);
        }
    }

    /**
     * 推送代码执行错误消息
     * 
     * @param sessionId 会话ID
     * @param error 错误信息
     * @param errorType 错误类型
     */
    public void sendExecutionError(String sessionId, String error, String errorType) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "execution_error");
            message.put("sessionId", sessionId);
            message.put("error", error);
            message.put("errorType", errorType);
            message.put("timestamp", System.currentTimeMillis());
            message.put("status", "执行出错");

            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送执行错误消息: sessionId={}, errorType={}", sessionId, errorType);
        } catch (Exception e) {
            log.error("发送执行错误消息失败", e);
        }
    }

    /**
     * 推送实时输出消息
     * 
     * @param sessionId 会话ID
     * @param output 输出内容
     */
    public void sendRealTimeOutput(String sessionId, String output) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "realtime_output");
            message.put("sessionId", sessionId);
            message.put("output", output);
            message.put("timestamp", System.currentTimeMillis());

            messagingTemplate.convertAndSend("/topic/execution/" + sessionId, message);
            
            log.debug("发送实时输出: sessionId={}, output length={}", sessionId, output.length());
        } catch (Exception e) {
            log.error("发送实时输出失败", e);
        }
    }

    /**
     * 推送系统状态消息
     * 
     * @param message 状态消息
     */
    public void sendSystemStatus(Map<String, Object> message) {
        try {
            message.put("type", "system_status");
            message.put("timestamp", System.currentTimeMillis());

            // 广播到所有连接的客户端
            messagingTemplate.convertAndSend("/topic/system", message);
            
            log.debug("发送系统状态消息: {}", message.get("status"));
        } catch (Exception e) {
            log.error("发送系统状态消息失败", e);
        }
    }

    /**
     * 推送用户通知消息
     * 
     * @param userId 用户ID
     * @param notification 通知内容
     */
    public void sendUserNotification(Long userId, Map<String, Object> notification) {
        try {
            notification.put("type", "user_notification");
            notification.put("timestamp", System.currentTimeMillis());

            // 发送到特定用户
            messagingTemplate.convertAndSendToUser(
                userId.toString(), 
                "/queue/notifications", 
                notification
            );
            
            log.debug("发送用户通知: userId={}, type={}", userId, notification.get("notificationType"));
        } catch (Exception e) {
            log.error("发送用户通知失败", e);
        }
    }

    /**
     * 推送代码分享通知
     * 
     * @param shareToken 分享令牌
     * @param codeTitle 代码标题
     * @param ownerName 所有者名称
     */
    public void sendCodeShareNotification(String shareToken, String codeTitle, String ownerName) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "code_share");
            message.put("shareToken", shareToken);
            message.put("codeTitle", codeTitle);
            message.put("ownerName", ownerName);
            message.put("timestamp", System.currentTimeMillis());
            message.put("status", "代码已分享");

            // 广播分享消息
            messagingTemplate.convertAndSend("/topic/shares", message);
            
            log.debug("发送代码分享通知: shareToken={}, title={}", shareToken, codeTitle);
        } catch (Exception e) {
            log.error("发送代码分享通知失败", e);
        }
    }

    /**
     * 推送在线用户统计
     * 
     * @param onlineCount 在线用户数
     * @param executingCount 正在执行代码的用户数
     */
    public void sendOnlineStatistics(int onlineCount, int executingCount) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "online_statistics");
            message.put("onlineCount", onlineCount);
            message.put("executingCount", executingCount);
            message.put("timestamp", System.currentTimeMillis());

            messagingTemplate.convertAndSend("/topic/statistics", message);
            
            log.debug("发送在线统计: online={}, executing={}", onlineCount, executingCount);
        } catch (Exception e) {
            log.error("发送在线统计失败", e);
        }
    }
}